
#include "AudioCore.h"
#include "../Logger.h"
#include "AudioSource.h"
#include <string>
#include <fstream>
#include <iostream>
#include <vector>

#define OV_EXCLUDE_STATIC_CALLBACKS
#include <vorbis/vorbisfile.h>

#ifdef __WIN32
#include <al.h>
#include <alc.h>
#include <list>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif

namespace al
{

AudioCore::AudioCore()
{
    //set the listener at 0,0,0 (3dxyz)
    alListener3f( AL_POSITION, 0.0f, 0.0f, 0.0f );
}

bool AudioCore::Initialize()
{
    //open device
    ALCdevice* device = alcOpenDevice( NULL );
    if( device )
    {
        //create context and bind it with the device
        ALCcontext* context = alcCreateContext( device, NULL );
        if( context )
        {
            alcMakeContextCurrent( context );
        }
        else
        {
            LOGERROR << "Error creating sound context.";
            alcCloseDevice( device );
            return false;
        }
    }
    else//error openin device
    {
        LOGERROR << "Error opening sound device.";
        return false;
    }

    // Clear Error Code (so we can catch any new errors)
    alGetError( );

    return true;
}

void AudioCore::Shutdown()
{
    ALCcontext* context;
    ALCdevice* device;

    context = alcGetCurrentContext( );
    device = alcGetContextsDevice( context );

    alcMakeContextCurrent( NULL );
    alcDestroyContext( context );
    alcCloseDevice( device );
}

AudioCore::~AudioCore()
{
    Shutdown( );
}

std::string AudioCore::ErrorStringOV(int code)
{
    switch( code )
    {
    case OV_EREAD:
        return std::string( "Read from media." );
    case OV_ENOTVORBIS:
        return std::string( "Not Vorbis data." );
    case OV_EVERSION:
        return std::string( "Vorbis version mismatch." );
    case OV_EBADHEADER:
        return std::string( "Invalid Vorbis header." );
    case OV_EFAULT:
        return std::string( "Internal logic fault (bug or heap/stack corruption." );
    default:
        return std::string( "Unknown Ogg error." );
    }
}

std::string AudioCore::ErrorStringAL(int code)
{
    switch( code )
    {
    case AL_OUT_OF_MEMORY:
        return std::string( "AL out of memory." );
    case AL_ILLEGAL_COMMAND:
        return std::string( "Ilegal or invalid command." );
    case AL_INVALID_VALUE:
        return std::string( "Invalid Vorbis header." );
    case AL_INVALID_ENUM:
        return std::string( "Ilegal or invalid enum." );
    case AL_INVALID_NAME:
        return std::string( "Invalid name." );
    default:
        return std::string( "Unknown Error." );
    }
}

bool AudioCore::Check()
{
    int error = alGetError( );
    if( error != AL_NO_ERROR )
    {
        LOG( Logger::CHANNEL_AUDIO, LogFileStream::LEVEL_ERROR ) << ErrorStringAL( error );
        return false;
    }
    return true;
}

void AudioCore::ClearErrorBuffer()
{
    alGetError( );
}

}
